//
//  T3FStringUtils.swift
//  t3_map
//
//  Created by zhu on 2024/11/22.
//

import Foundation
import UIKit

extension String {
    /// 从某个位置开始截取：
    /// - Parameter index: 起始位置
    func substring(from index: Int) -> String {
        if self.count > index {
            let startIndex = self.index(self.startIndex, offsetBy: index)
            let subString = self[startIndex..<self.endIndex]
            return String(subString)
        } else {
            return ""
        }
    }
}

extension Array {

    /// 取数组中指定脚标数据
    /// - Parameter safe: 获取数组中元素的脚标
    subscript(safe index: Int) -> Element? {

        guard index >= 0 && self.count > index else {
            return nil
        }

        return self[index]
    }
}

public struct T3AttributeElement {
    public var font: UIFont?
    public var color: UIColor?
    public var baselineOffset: CGFloat?
    public init(font: UIFont?, color: UIColor?, baselineOffset: CGFloat? = nil) {
        self.font = font
        self.color = color
        self.baselineOffset = baselineOffset
    }

    var attributes: [NSAttributedString.Key : Any] {
        var dic = [NSAttributedString.Key : Any]()
        if let color = color {
            dic[.foregroundColor] = color
        }
        if let font = font {
            dic[.font] = font
        }
        if let baselineOffset = baselineOffset {
            dic[.baselineOffset] = baselineOffset
        }
        return dic
    }
}

public extension NSAttributedString {
    /// 项目符号列表
    /// - Parameters:
    ///   - bullet: 符号样式
    ///   - indentation: 缩进距离
    ///   - lineSpacing: 行间距
    ///   - paragraphSpacing: 段落间距
    /// - Returns: 项目符号列表
    static func attributeString(stringList: [String],
                                font: UIFont,
                                bullet: String = "\u{2022}",
                                indentation: CGFloat = 16,
                                lineSpacing: CGFloat = 1,
                                paragraphSpacing: CGFloat = 12,
                                lineBreakMode: NSLineBreakMode = .byWordWrapping,
                                textColor: UIColor,
                                bulletColor: UIColor) -> NSAttributedString {

        let textAttributes = [NSAttributedString.Key.font: font,
                              NSAttributedString.Key.foregroundColor: textColor]
        let bulletAttributes = [NSAttributedString.Key.font: font,
                                NSAttributedString.Key.foregroundColor: bulletColor]

        let paragraphStyle = NSMutableParagraphStyle()
        let nonOptions = [NSTextTab.OptionKey: Any]()
        paragraphStyle.tabStops = [NSTextTab(textAlignment: .left,
                                             location: indentation,
                                             options: nonOptions)]
        paragraphStyle.defaultTabInterval = indentation
        //paragraphStyle.firstLineHeadIndent = 0
        //paragraphStyle.headIndent = 20
        //paragraphStyle.tailIndent = 1
        paragraphStyle.lineSpacing = lineSpacing
        paragraphStyle.paragraphSpacing = paragraphSpacing
        paragraphStyle.headIndent = indentation
        paragraphStyle.lineBreakMode = lineBreakMode

        let bulletList = NSMutableAttributedString()
        for (index, string) in stringList.enumerated() {
            var formattedString = "\(bullet)\t\(string)"
            // 最后一行不要换行
            if index != stringList.count - 1 {
                formattedString += "\n"
            }
            let attributedString = NSMutableAttributedString(string: formattedString)

            // 缩进文本
            attributedString.addAttributes(
                [NSAttributedString.Key.paragraphStyle : paragraphStyle],
                range: NSMakeRange(0, attributedString.length))
            attributedString.addAttributes(
                textAttributes,
                range: NSMakeRange(0, attributedString.length))

            // 在文本前增加符号
            let string:NSString = NSString(string: formattedString)
            let rangeForBullet:NSRange = string.range(of: bullet)
            attributedString.addAttributes(bulletAttributes, range: rangeForBullet)

            bulletList.append(attributedString)
        }

        return bulletList
    }

}

public extension NSAttributedString {
    /// 自动处理数字高亮，
    ///
    ///     示例：8.5折，8.5加粗、高亮
    ///
    /// - Parameters:
    ///   - numberString: 可能包含数字的字符串
    ///   - normal: 非数字属性
    ///   - hilight: 数字属性
    /// - Returns: 高亮后字符串
    static func attributeString(numberString: String?,
                         normal: T3AttributeElement,
                         hilight: T3AttributeElement) -> NSAttributedString? {
        guard let numberString = numberString,
              let regular = try? NSRegularExpression(pattern: "([0-9]\\d*\\.?\\d*)", options: []) else {
            return nil
        }

        let ranges: Array = regular.matches(in: numberString,
                                            options: [],
                                            range: NSRange(location: 0, length: numberString.count))

        let attStr = NSMutableAttributedString(string: numberString,
                                               attributes: normal.attributes)

        let hiliteAttributes = hilight.attributes
        for index in 0..<ranges.count {
            attStr.setAttributes(hiliteAttributes, range: ranges[index].range)
        }
        return attStr
    }
}

public extension NSAttributedString {

    /// 处理##之间字符高亮
    ///
    ///     示例：再完成#1#单即可领取#5个T币#
    ///
    /// - Parameters:
    ///   - string: 需要高亮##之间字符的字符串
    ///   - attribute: 非##之间字符串属性
    ///   - hilightAttribute: ##之间字符串属性
    /// - Returns: 高亮后字符串
    class func attributeString(string: String?,
                               normal: T3AttributeElement,
                               hilight: T3AttributeElement) -> NSAttributedString? {
        return attributeString(string: string,
                               attribute: normal,
                               hilightAttribute: hilight)
    }

    class func attributeString(string: String?,
                               attribute: (font: UIFont, color: UIColor),
                               hilightAttribute: (font: UIFont, color: UIColor)) -> NSAttributedString? {
        return attributeString(string: string,
                               attribute: T3AttributeElement(font: attribute.font, color: attribute.color),
                               hilightAttribute: T3AttributeElement(font: hilightAttribute.font, color: hilightAttribute.color))
    }

    class func attributeString(string: String?,
                               attribute: T3AttributeElement,
                               hilightAttribute: T3AttributeElement) -> NSAttributedString? {

        guard var string = string else {
            return nil
        }

        if string.contains("##") {
            string = string.replacingOccurrences(of: "##", with: "")
        }
        guard string.contains("#") else {
            return NSAttributedString(string: string, attributes: [.font: attribute.font ?? UIFont(), .foregroundColor: attribute.color ?? UIColor()])
        }

        let array = string.components(separatedBy: "#")
        let result = NSMutableAttributedString(string: "")
        var current = string
        for item in array {
            if current.hasPrefix(item) {
                // 非##之间
                result.append(genAttribute(string: item, attribute: attribute))
                current = current.substring(from: item.count)
            } else {
                // ##之间
                result.append(genAttribute(string: item, attribute: hilightAttribute))
                current = current.substring(from: item.count + 2)
            }
        }
        return result
    }
}

public extension NSAttributedString {
    /// 处理%s字符替换及高亮
    ///
    ///     示例：再完成%s单即可领取%@
    ///
    /// - Parameters:
    ///   - string: 包含%s的字符串
    ///   - replaces: 替换%s的字符串数组，顺序替换
    ///   - attribute: 非%s部分字符串属性
    ///   - hilightAttribute: %s字符串属性
    /// - Returns: 替换及高亮后字符串
    class func attributeString(string: String?,
                               replaceStrings: [String],
                               attribute: (font: UIFont, color: UIColor),
                               hilightAttribute: (font: UIFont, color: UIColor)) -> NSAttributedString? {
        return attributeString(string: string,
                               replaceStrings: replaceStrings,
                               attribute: T3AttributeElement(font: attribute.font, color: attribute.color),
                               hilightAttribute: T3AttributeElement(font: hilightAttribute.font, color: hilightAttribute.color))
    }

    class func attributeString(string: String?,
                               replaceStrings: [String], attribute: T3AttributeElement,
                               hilightAttribute: T3AttributeElement) -> NSAttributedString? {
        guard let string = string else {
            return nil
        }

        // 拆分
        let subStrings:[String] = string.components(separatedBy: "%s")

        // 一个
        guard subStrings.count > 1 else {
            return genAttribute(string: string, attribute: attribute)
        }

        // 校验%s个数和要替换的数组的个数是否匹配
        if subStrings.count != replaceStrings.count + 1 {
            return nil
        }

        let result:NSMutableAttributedString = NSMutableAttributedString()

        // 拼凑字符串
        for index in 0...(subStrings.count - 1) {

            let subAttributeString = genAttribute(string: subStrings[safe: index] ?? "", attribute: attribute)
            result.append(subAttributeString)
            // 非最后一个
            if index < replaceStrings.count, let replaceString = replaceStrings[safe: index] {
                let replaceAttibuteString = genAttribute(string: replaceString, attribute: hilightAttribute)
                result.append(replaceAttibuteString)
            }
        }

        return result
    }
}

private extension NSAttributedString {
    class func genAttribute(string: String, attribute: T3AttributeElement) -> NSAttributedString {
        var dic = [NSAttributedString.Key : Any]()
        if attribute.color != nil {
            dic[.foregroundColor] = attribute.color ?? UIColor()
        }
        if attribute.font != nil {
            dic[.font] = attribute.font ?? UIFont()
        }
        if attribute.baselineOffset != nil {
            dic[.baselineOffset] = attribute.baselineOffset ?? 0
        }

        return NSAttributedString(string: string, attributes: dic)
    }
}

public extension NSAttributedString {
    class func attributedDoubleWith(_ doubleStr: String,
                              normalAttribute: (font: UIFont, color: UIColor),
                              specialAttribute: (font: UIFont, color: UIColor)) -> NSAttributedString? {
        let subDoubleStrs = doubleStr.components(separatedBy: ".")

        if subDoubleStrs[safe: 0] == nil && subDoubleStrs[safe: 1] == nil {
            return nil
        }

        let attributedStr = NSMutableAttributedString()

        if let integerStr = subDoubleStrs[safe: 0] {
            attributedStr.append(NSAttributedString(string: integerStr,
                                                    attributes: [.font: normalAttribute.font,
                                                                 .foregroundColor: normalAttribute.color]))
        }

        if let decimalsStr = subDoubleStrs[safe: 1] {
            attributedStr.append(NSAttributedString(string: ".\(decimalsStr)",
                                                    attributes: [.font: specialAttribute.font,
                                                                 .foregroundColor: specialAttribute.color]))
        }

        return attributedStr
    }
}
